<script setup lang="ts">
import { CreatedSame } from "@/api/drawing"
import debounce from "@/utils/debounce"
import { ElMessage } from "element-plus"
import Pubsub from "pubsub-js"
import { computed, ref, shallowRef, watch, watchPostEffect } from "vue"

interface ImageProps {
  id: number
  src: string
}

interface WaterFallProps {
  images: ImageProps[] // 图片数组
  columnCount?: number // 要划分的列数
  columnGap?: number // 各列之间的间隙，单位px
}

const props = withDefaults(defineProps<Partial<WaterFallProps>>(), {
  images: () => [],
  columnCount: 2,
  columnGap: 20,
  width: "100%"
})

const imagesProperty = ref<any[]>([])
const preColumnHeight = ref<number[]>(Array(props.columnCount).fill(0)) // 每列的高度
const waterfall = shallowRef() // ref() 的浅层作用形式
const imageWidth = ref()
const rerender = ref(false)

const len = computed(() => {
  return props.images.length
})

watch(
  () => [props.columnCount, props.columnGap, props.width],
  () => {
    rerender.value = true
    preColumnHeight.value = Array(props.columnCount).fill(0)
    onPreload()
  },
  {
    deep: true, // 强制转成深层侦听器
    flush: "post" // 在侦听器回调中访问被 Vue 更新之后的 DOM
  }
)
watchPostEffect(() => {
  if (props.images.length) {
    onPreload()
  }
})
async function onPreload() {
  // 计算每列的图片宽度
  // imageWidth.value = (waterfall.value.offsetWidth - (props.columnCount + 1) * props.columnGap) / props.columnCount
  // 计算每列的图片宽度
  for (let i = 0; i < len.value; i++) {
    await loadImage(props.images[i].src, i)
  }
}
function loadImage(url: string, n: number) {
  return new Promise((resolve) => {
    const image = new Image()
    image.src = url
    // 图片加载完成时执行，此时可通过image.width和image.height获取到图片原始宽高
    image.onload = function () {
      const height = image.height / (image.width / imageWidth.value)
      // 存储图片宽高和位置信息
      imagesProperty.value[n] = {
        height: height
      }
      resolve("load")
    }
  })
}

const handleCreateTheSame = debounce(async (id: number) => {
  try {
    const result = await CreatedSame({ id })
    if (result.code === 200) {
      ElMessage({
        type: "success",
        message: "创建成功，等待绘画图片生成..."
      })
      Pubsub.publish("UPDATE_DATA_INIT")
    } else {
      ElMessage({
        type: "error",
        message: result.error
      })
    }
  } catch (error) {
    console.error(error)
  }
}, 300)
</script>

<template>
  <div class="m-waterfall" ref="waterfall">
    <div
      class="m-image"
      v-for="(property, index) in imagesProperty"
      :key="index"
      :style="`height: ${property.height}px;`"
    >
      <img class="u-image" :src="images[index].src" />
      <el-button class="btn" @click="handleCreateTheSame(images[index].id)">创造同款</el-button>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.m-waterfall {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;

  .m-image {
    width: 48%;
    margin-bottom: 10px;

    .u-image {
      width: 100%;
      border-radius: 6px;
      vertical-align: bottom;
    }

    .btn {
      width: 100%;
      height: 40px;
      margin-top: 10px;
      background: var(--v3-body-bg-color);
      border: unset !important;
    }
  }
}
</style>
